package order

import (
	"context"
	// "fmt"
	"strconv"
	"strings"

	"mall/common/globalkey"
	"mall/common/jwt"
	"mall/common/moneyx"
	"mall/common/resultx"
	"mall/common/uniqueidx"
	"mall/common/utils/pointy"
	"mall/service/forum/api/internal/logic/util"
	"mall/service/forum/api/internal/svc"
	"mall/service/forum/api/internal/types"
	"mall/service/order/rpc/orderclient"
	"mall/service/product/rpc/productclient"

	// "github.com/sirupsen/logrus"
	"github.com/wechatpay-apiv3/wechatpay-go/core"
	"github.com/wechatpay-apiv3/wechatpay-go/services/refunddomestic"
	"github.com/zeromicro/go-zero/core/logx"
)

type RefundOrderLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewRefundOrderLogic(ctx context.Context, svcCtx *svc.ServiceContext) *RefundOrderLogic {
	return &RefundOrderLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *RefundOrderLogic) RefundOrder(
	req *types.IDReq,
	headers *[]*types.Header,
) (resp *types.RefundOrderResp, err error) {
	userId := jwt.GetUserId(l.ctx)
	if userId == 0 {
		return nil, resultx.NewErrCode(resultx.TOKEN_EXPIRE_ERROR)
	}

	preload := "order:Id,ActualAmount,TradeState,OrderType"
	preload += ";orderPayment:Id,No,TransactionID,Amount,Type"
	preload += ";orderItem:Id,SkuId,Quantity"
	eagerLoad := "order:orderPayment,orderItem"
	var filters []string
	filters = append(filters, "Id,equalTo:"+strconv.FormatInt(int64(req.Id), 10))
	filters = append(filters, "UserId,equalTo:"+strconv.FormatInt(int64(userId), 10))
	filters = append(filters, "TradeState,equalTo:"+strconv.FormatInt(int64(globalkey.OrderTradeStatePaid), 10))
	var platformId uint32 = globalkey.ThirdPartyPlatformWechatMini

	order, err := l.svcCtx.OrderRpc.GetOrderById(l.ctx, &orderclient.BaseIdReq{
		Preload:    pointy.GetPointer(preload),
		EagerLoad:  pointy.GetPointer(eagerLoad),
		Filter:     pointy.GetPointer(strings.Join(filters, ";")),
		VisitorId:  pointy.GetPointer(userId),
		PlatformId: pointy.GetPointer(platformId),
	})
	if err != nil {
		logx.Errorw("RefundOrder GetOrderById err", logx.Field("detail", err.Error()))
		return nil, resultx.NewErrCode(resultx.ORDER_PARAM_INVALID)
	}

	if order == nil || order.Id == nil || *order.Id == 0 || len(order.Payments) == 0 {
		return nil, resultx.NewErrCode(resultx.ORDER_PARAM_INVALID)
	}

	if len(order.Skus) > 0 && *order.OrderType != globalkey.OrderTypeVirtual {
		var stocks []*productclient.ProductVariationStock
		for _, v := range order.Skus {
			if v.SkuId != nil && v.Quantity != nil && *v.SkuId > 0 && *v.Quantity > 0 {
				stocks = append(stocks, &productclient.ProductVariationStock{
					Id:    *v.SkuId,
					Stock: *v.Quantity,
				})
			}
		}
		if len(stocks) > 0 {
			_, err = l.svcCtx.ProductRpc.SubtractStockRevert(l.ctx, &productclient.CheckAndSubtractStockReq{
				Data: stocks,
			})
			if err != nil {
				logx.Errorw("RefundOrder SubtractStockRevert err", logx.Field("detail", err.Error()))
				// return &types.RefundOrderResp{
				// 	Msg: "操作失败",
				// }, nil
			}
		}
	}

	var sn string
	var transactionId string
	var amount string
	var paymentType uint32
	payment := order.Payments[0]
	if payment.No != nil && len(*payment.No) > 0 {
		sn = *payment.No
	}
	if payment.TransactionID != nil && len(*payment.TransactionID) > 0 {
		transactionId = *payment.TransactionID
	}
	if payment.Amount != nil && len(*payment.Amount) > 0 {
		amount = *payment.Amount
	}
	if payment.Type != nil && *payment.Type > 0 {
		paymentType = *payment.Type
	}

	var finalAmountFen int64
	if fa, err := moneyx.ParseDecimal(amount); err != nil {
		return nil, resultx.NewErrCode(resultx.ORDER_PARAM_INVALID)
	} else {
		finalAmountFen = moneyx.FormatDecimalToFen(fa)
		// logrus.Info(fmt.Sprintf("RefundOrder finalAmountFen: %+v", finalAmountFen))
	}

	var refundNo string
	var refund *orderclient.OrderRefundInfo
	if paymentType == globalkey.PaymentTypeWeChatPay {
		// 微信支付
		refundNo = uniqueidx.GenSn(uniqueidx.SN_PREFIX_THIRD_PART_REFUND)
		refund = &orderclient.OrderRefundInfo{
			PaymentId: payment.Id,
			RefundNo:  pointy.GetPointer(refundNo),
			Amount:    payment.Amount,
			Status:    pointy.GetPointer(globalkey.PaymentStatusUserClosed),
		}
	} else if paymentType == globalkey.PaymentTypeGems {
		// 宝石支付
		refundNo = uniqueidx.GenSn(uniqueidx.SN_PREFIX_GEM_REFUND)
		refund = &orderclient.OrderRefundInfo{
			PaymentId: payment.Id,
			RefundNo:  pointy.GetPointer(refundNo),
			Amount:    payment.Amount,
			Status:    pointy.GetPointer(globalkey.PaymentStatusUserClosed),
		}
	} else {
		return nil, resultx.NewErrCode(resultx.ORDER_PARAM_INVALID)
	}

	newPayment := &orderclient.OrderPaymentInfo{
		Id:     payment.Id,
		Status: pointy.GetPointer(globalkey.PaymentStatusUserClosed),
	}

	// 3. 修改订单
	tradeState := pointy.GetPointer(globalkey.OrderTradeStateClosed)
	_, err = l.svcCtx.OrderRpc.UpdateOrder(l.ctx, &orderclient.OrderInfo{
		Id:         order.Id,
		UserId:     pointy.GetPointer(userId),
		TradeState: tradeState,
		NewPayment: newPayment,
		NewRefund:  refund,
	})
	if err != nil {
		return nil, err
	}

	err = l.createRefund(paymentType, sn, transactionId, refundNo, finalAmountFen)
	if err != nil {
		return nil, err
	}

	option := util.GetOptionByStatus(tradeState)

	return &types.RefundOrderResp{
		Option: &types.TradeInfoFragment{
			TradeState:     tradeState,
			TradeStateText: util.GetTradeStateText(tradeState),
			CanCancel:      option.CanCancel,
			CanPay:         option.CanPay,
			CanRefund:      option.CanRefund,
			CanRemind:      option.CanRemind,
			CanTrack:       option.CanTrack,
			CanConfirm:     option.CanConfirm,
			CanInvoice:     option.CanInvoice,
			CanRemove:      option.CanRemove,
		},
	}, nil
}

func (l *RefundOrderLogic) createRefund(
	paymentType uint32,
	sn string,
	transactionId string,
	refundNo string,
	amount int64,
) error {
	if paymentType == globalkey.PaymentTypeWeChatPay {
		err := l.createWxDomesticRefund(sn, transactionId, refundNo, amount)
		if err != nil {
			return err
		}
	}

	return nil
}

func (l *RefundOrderLogic) createWxDomesticRefund(
	sn string,
	transactionId string,
	refundNo string,
	amount int64,
) error {
	wxPayClient, err := svc.NewWxPayClientV3(l.svcCtx.Config)
	if err != nil {
		logx.Errorw("create wechat pay domestic refund, init err", logx.Field("detail", err.Error()))
		return resultx.NewErrCode(resultx.PAYMENT_WECHAT_PAY_INIT_PRE_ORDER_FAIL)
	}

	jsApiSvc := refunddomestic.RefundsApiService{Client: wxPayClient}
	resp, result, err := jsApiSvc.Create(l.ctx, refunddomestic.CreateRequest{
		// SubMchid:      core.String(l.svcCtx.Config.WxPayConf.MchId),
		TransactionId: core.String(transactionId),
		OutTradeNo:    core.String(sn),
		OutRefundNo:   core.String(refundNo),
		// Reason:        core.String("商品已售完"),
		Reason:       core.String("用户取消订单"),
		NotifyUrl:    core.String(l.svcCtx.Config.WxPayConf.RefundNotifyUrl),
		FundsAccount: refunddomestic.REQFUNDSACCOUNT_AVAILABLE.Ptr(),
		Amount: &refunddomestic.AmountReq{
			Currency: core.String("CNY"),
			// From: []refunddomestic.FundsFromItem{refunddomestic.FundsFromItem{
			// 	Account: refunddomestic.ACCOUNT_AVAILABLE.Ptr(),
			// 	Amount:  core.Int64(amount),
			// }},
			Refund: core.Int64(amount),
			Total:  core.Int64(amount),
		},
		// GoodsDetail: []refunddomestic.GoodsDetail{refunddomestic.GoodsDetail{
		// 	GoodsName:        core.String("iPhone6s 16G"),
		// 	MerchantGoodsId:  core.String("1217752501201407033233368018"),
		// 	RefundAmount:     core.Int64(528800),
		// 	RefundQuantity:   core.Int64(1),
		// 	UnitPrice:        core.Int64(528800),
		// 	WechatpayGoodsId: core.String("1001"),
		// }}},
	})
	if err != nil {
		//处理错误
		logx.Errorw("call Create err", logx.Field("detail", err.Error()))
		// error http response:[StatusCode: 400 Code: \"PARAM_ERROR\"\nMessage: 输入源“/body/transaction_id”映射到值字段“微信支付订单号”字符串规则校验失败，字符数 0，小于最小值 1\nDetail:\n{\n  \"location\": \"body\",\n  \"value\": 0\n}\nHeader:\n - Date=[Wed, 09 Oct 2024 09:42:01 GMT]\n - Keep-Alive=[timeout=8]\n - Wechatpay-Nonce=[02312be8246edf6b2e929241373c9a2d]\n - Content-Language=[zh-CN]\n - Wechatpay-Timestamp=[1728466920]\n - Wechatpay-Signature-Type=[WECHATPAY2-SHA256-RSA2048]\n - Connection=[keep-alive]\n - Wechatpay-Signature=[m34qs/T4WZ0cuhaviJmC467FBXBKPuPBWeEG9xMqIFwvDe7URScAZHsWWuIuEiGR/8Mo0BSqIhulun24uDMu3ilTjaBuku8MbBota2xS4Q2vwB/RR5xxTX7InGRmqfFkqgZBzpR1fL+EeSIE7mirFDCu5WoSXHFgDtVvL9PbCRabIGEIdYGE9lWEifboW1eLNNnIVDWwDXf9ZK3q9xtK4SwyK1JCQGIOAksawengGO38XVHE3TA3TEfkTbUGjScZlAVqR2863WB21Mdf/BnrAC0KpTtuHT7x0SVZDZwW25xu11ujlB1dj++aPRl0nJP4QTu89/5WwHfw0FmWUigxeg==]\n - Wechatpay-Serial=[2AA63715322A5A193DD9FF5C9C2F9F50917FFF8E]\n - Cache-Control=[no-cache, must-revalidate]\n - X-Content-Type-Options=[nosniff]\n - Request-Id=[08E89F99B80610A10718A7BCC05520B02428D1BA02-268435463]\n - Server=[nginx]\n - Content-Type=[application/json; charset=utf-8]\n - Content-Length=[215]]
		// error http response:[StatusCode: 400 Code: \"PARAM_ERROR\"\nMessage: invalid use both funds from and account param\nHeader:\n - Date=[Wed, 09 Oct 2024 09:52:00 GMT]\n - Content-Length=[80]\n - Keep-Alive=[timeout=8]\n - Content-Language=[zh-CN]\n - Wechatpay-Signature=[YMZ2X+FczYT/3/QkvSsBc8aqG8fTxKD67avejvOF0tIJMHGioMpLJxpMk9/EBBzlmpYVq6b2CKndTbMUlUFPkKuKry/SHSWkJjGwkRVzHG5eLCUSw7a9OWW6z7c5FaGorUQmaqbKxzl6Y4f+qipfUgEQsVMenywrm053nMVQO5YM3lbPrTIHfDxrLJbMpUa5nJJsAVX3MKrfGi021UOwNomtld22h7ersrIQgoWXolgnwCj2G2R4rawvK2198urzSjDZXDhfbTmWOMdFBLOlc73l/ZP0bLRSuR2s2icg5RtEIdK15mXss7WobwbhF/yx/VQoX0eRyLplNjhOwKJa8g==]\n - Wechatpay-Timestamp=[1728467520]\n - Wechatpay-Serial=[2AA63715322A5A193DD9FF5C9C2F9F50917FFF8E]\n - Wechatpay-Signature-Type=[WECHATPAY2-SHA256-RSA2048]\n - Server=[nginx]\n - Content-Type=[application/json; charset=utf-8]\n - Cache-Control=[no-cache, must-revalidate]\n - X-Content-Type-Options=[nosniff]\n - Request-Id=[08C0A499B80610AF0318D2C38C5820894528D7BB05-268444752]\n - Wechatpay-Nonce=[f1b7299591e3728ba1c6cdab52c0c945]\n - Connection=[keep-alive]]
		// error http response:[StatusCode: 400 Code: \"PARAM_ERROR\"\nMessage: 普通商户不允许传sub_mch_id\nHeader:\n - Content-Language=[zh-CN]\n - Wechatpay-Timestamp=[1728468102]\n - Cache-Control=[no-cache, must-revalidate]\n - Content-Type=[application/json; charset=utf-8]\n - Content-Length=[69]\n - Keep-Alive=[timeout=8]\n - X-Content-Type-Options=[nosniff]\n - Request-Id=[0886A999B80610FC0618FCB3C05520D57928F9E705-268443744]\n - Wechatpay-Signature=[YpOpoAS2XuxPLemk/KR17OSLppOlvLbQLBNTOzb8PsSBdqwAl/wTm/LX6NGTmvdox5Lf60I78/De+vklUve5tBb2opJaT+BeTtr5y7EcZfklbTD2hVkk6uF5X/x8Pf/DShyQt+MoJr7oMsamq2gAwbPtLXoJuf6iGLXbjwq1+VeXmlpk08NgInWSqR04mjV9w8/ajGhMO5XX9imJwX/fyVMSAPM8J6WrNnzWfH+rx9qYw+XiqgSaTD8lfrQOdA9EiHXkIJFsQY5iOPoGSa2pLcZINLPB4xNJFe3zIuq88obtsbIq3T6U8fB6L43sQrkxW1RoUzIQNktHCWkQzsTNlg==]\n - Wechatpay-Serial=[2AA63715322A5A193DD9FF5C9C2F9F50917FFF8E]\n - Server=[nginx]\n - Wechatpay-Signature-Type=[WECHATPAY2-SHA256-RSA2048]\n - Connection=[keep-alive]\n - Date=[Wed, 09 Oct 2024 10:01:42 GMT]\n - Wechatpay-Nonce=[11d328f074976b9c270acdc6afef0c80]]
		return resultx.NewErrCode(resultx.PAYMENT_WECHAT_REFUND_FAIL)
	} else {
		//处理返回结果
		logx.Infow(
			"call Create",
			logx.Field("status", result.Response.StatusCode),
			logx.Field("resp", resp),
		)
	}

	return nil
}
